<!--
  文件级注释：分账记录页面
  - 用户视角与商户视角查看分账记录
  - 支持时间范围、协议/商户/收款码筛选
  规则：返回值 code === 0 视为成功
-->

<template>
  <div class="container divided-records">
    <div class="page-header">
      <h1>分账记录</h1>
      <div class="segmented">
        <button class="segmented-item" :class="{ active: activeTab==='user' }" @click="activeTab='user'">用户视角</button>
        <button class="segmented-item" :class="{ active: activeTab==='merchant' }" @click="activeTab='merchant'">商户视角</button>
      </div>
    </div>

    <!-- 用户视角筛选 -->
    <div v-if="activeTab==='user'" class="filters card">
      <label>
        开始时间：
        <input v-model="userFilter.startTime" class="input" type="datetime-local" />
      </label>
      <label>
        结束时间：
        <input v-model="userFilter.endTime" class="input" type="datetime-local" />
      </label>
      <button class="btn primary" @click="fetchUserRecords">查询</button>
    </div>

    <!-- 商户视角筛选 -->
    <div v-else class="filters card">
      <label>
        分账日期：
        <input v-model="merchantFilter.dividedDate" class="input" type="date" />
      </label>
      <label>
        商户ID：
        <input v-model="merchantFilter.merchantId" class="input" />
      </label>
      <label>
        协议ID：
        <input v-model="merchantFilter.dividedAgreementId" class="input" />
      </label>
      <label>
        收款码ID：
        <input v-model="merchantFilter.codeId" class="input" />
      </label>
      <button class="btn primary" @click="fetchMerchantRecords">查询</button>
    </div>

    <!-- 记录列表 -->
    <div class="card table-wrapper">
    <table class="table">
      <thead>
        <tr>
          <th>分账日期</th>
          <th>协议ID</th>
          <th>协议名称</th>
          <th>创建时间</th>
          <th>商户ID</th>
          <th>收款码ID</th>
          <th>订单ID</th>
          <th>分账总额(元)</th>
          <th>操作</th>
        </tr>
      </thead>
        <tbody>
        <tr v-for="r in records" :key="r.Id || r.id" class="table-row">
          <td>{{ formatYMD(r.dividedDate) }}</td>
          <td class="mono"><span class="ellipsis copyable" :title="r.dividedAgreementId || '-'" @click="copyText(r.dividedAgreementId)">{{ shortId(r.dividedAgreementId) }}</span></td>
          <td>{{ r.dividedAgreementName || '-' }}</td>
          <td><span class="ellipsis copyable" :title="formatDateTime(r.creationTime)" @click="copyText(formatDateTime(r.creationTime))">{{ shortTime(r.creationTime) }}</span></td>
          <td class="mono"><span class="ellipsis copyable" :title="r.merchantId || '-'" @click="copyText(r.merchantId)">{{ shortId(r.merchantId) }}</span></td>
          <td class="mono"><span class="ellipsis copyable" :title="r.codeId || '-'" @click="copyText(r.codeId)">{{ shortId(r.codeId) }}</span></td>
          <td class="mono"><span class="ellipsis copyable" :title="r.orderId || '-'" @click="copyText(r.orderId)">{{ shortId(r.orderId) }}</span></td>
          <td>{{ formatCents(r.totalDividedAmount) }}</td>
          <td>
            <router-link class="btn ghost" :to="`/divided-records/detail/${r.id || r.Id}`">查看详情</router-link>
          </td>
        </tr>
        <tr v-if="records.length === 0">
          <td colspan="9" class="empty">暂无记录</td>
        </tr>
      </tbody>
    </table>
    </div>

    <!-- 分页 -->
    <div class="pagination card">
      <button class="btn" :disabled="pager.page<=1" @click="onPrev">上一页</button>
      <span>第 {{ pager.page }} / {{ totalPages }} 页</span>
      <button class="btn" :disabled="pager.page>=totalPages" @click="onNext">下一页</button>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, onMounted } from 'vue'
import { DividedService } from '../services/divided'
import { isSuccess } from '../services/types'

/** 组件级注释：按不同视角查询和展示分账记录 */

/** 当前视图 */
const activeTab = ref<'user' | 'merchant'>('user')
/** 记录列表 */
const records = ref<any[]>([])
/** 分页状态 */
const pager = ref({ page: 1, limit: 10, total: 0 })
/** 总页数 */
const totalPages = computed(() => Math.max(1, Math.ceil(pager.value.total / pager.value.limit)))

/** 用户视角筛选 */
const userFilter = ref({ startTime: '', endTime: '' })
/** 商户视角筛选（与后端参数命名保持一致） */
const merchantFilter = ref({ dividedDate: '', merchantId: '', dividedAgreementId: '', codeId: '' })

/**
 * 函数级注释：获取用户视角分账记录
 * @returns Promise<void>
 */
/**
 * 函数级注释：获取用户视角分账记录
 * @returns Promise<void>
 * @throws 可能抛出网络异常
 */
async function fetchUserRecords(): Promise<void> {
  // 校验时间范围，避免传递空值导致后端 400 验证错误
  if (!validateUserRange()) return
  const res = await DividedService.getUserDividedRecordList(
    userFilter.value.startTime,
    userFilter.value.endTime,
    pager.value.page,
    pager.value.limit,
  )
  if (isSuccess(res)) {
    records.value = res.data?.data || []
    pager.value.total = res.data?.total || 0
  } else {
    alert(res.message || '获取用户视角分账记录失败')
  }
}

/**
 * 函数级注释：获取商户视角分账记录
 * @returns Promise<void>
 */
/**
 * 函数级注释：获取商户视角分账记录
 * @returns Promise<void>
 * @throws 可能抛出网络异常
 */
async function fetchMerchantRecords(): Promise<void> {
  // 校验分账日期，避免传递空值导致后端 400 验证错误
  if (!validateMerchantFilter()) return
  const res = await DividedService.getMerchantDividedRecordList(
    merchantFilter.value.dividedDate,
    pager.value.page,
    pager.value.limit,
    merchantFilter.value.merchantId,
    merchantFilter.value.dividedAgreementId,
    merchantFilter.value.codeId,
  )
  if (isSuccess(res)) {
    records.value = res.data?.data || []
    pager.value.total = res.data?.total || 0
  } else {
    alert(res.message || '获取商户视角分账记录失败')
  }
}

/** 切换标签后重置分页并查询 */
function refresh(): void {
  pager.value.page = 1
  activeTab.value === 'user' ? fetchUserRecords() : fetchMerchantRecords()
}

function onPrev(): void { if (pager.value.page > 1) { pager.value.page--; refresh() } }
function onNext(): void { if (pager.value.page < totalPages.value) { pager.value.page++; refresh() } }

// 记录状态字段不在当前列表返回中，若后端补充可在此格式化显示
/**
 * 函数级注释：校验用户视角时间范围
 * @returns boolean 是否通过校验
 */
function validateUserRange(): boolean {
  const { startTime, endTime } = userFilter.value
  if (!startTime || !endTime) {
    alert('请选择开始时间与结束时间')
    return false
  }
  if (new Date(startTime).getTime() > new Date(endTime).getTime()) {
    alert('开始时间不能大于结束时间')
    return false
  }
  return true
}

/**
 * 函数级注释：校验商户视角筛选
 * @returns boolean 是否通过校验
 */
function validateMerchantFilter(): boolean {
  if (!merchantFilter.value.dividedDate) {
    alert('请选择分账日期')
    return false
  }
  return true
}

/**
 * 函数级注释：格式化 Date 为 <input type="datetime-local"> 值
 * @param d 日期对象
 * @returns string 形如 YYYY-MM-DDTHH:mm
 */
function formatDateTimeLocal(d: Date): string {
  const pad = (n: number) => String(n).padStart(2, '0')
  const y = d.getFullYear()
  const m = pad(d.getMonth() + 1)
  const day = pad(d.getDate())
  const h = pad(d.getHours())
  const min = pad(d.getMinutes())
  return `${y}-${m}-${day}T${h}:${min}`
}

/**
 * 函数级注释：格式化 Date 为 <input type="date"> 值
 * @param d 日期对象
 * @returns string 形如 YYYY-MM-DD
 */
function formatDateLocal(d: Date): string {
  const pad = (n: number) => String(n).padStart(2, '0')
  const y = d.getFullYear()
  const m = pad(d.getMonth() + 1)
  const day = pad(d.getDate())
  return `${y}-${m}-${day}`
}

/**
 * 函数级注释：初始化默认筛选值并触发查询
 */
onMounted(() => {
  // 用户视角默认近 7 天
  if (!userFilter.value.startTime || !userFilter.value.endTime) {
    const end = new Date()
    const start = new Date(end.getTime() - 7 * 24 * 60 * 60 * 1000)
    userFilter.value.startTime = formatDateTimeLocal(start)
    userFilter.value.endTime = formatDateTimeLocal(end)
  }
  // 商户视角默认当天
  if (!merchantFilter.value.dividedDate) {
    merchantFilter.value.dividedDate = formatDateLocal(new Date())
  }
  refresh()
})

/**
 * 函数级注释：格式化字符串/日期为 年-月-日 展示
 * @param d 日期字符串或 Date
 * @returns string 形如 YYYY-MM-DD；入参为空时返回 '-'
 * @throws 无显式异常（内部使用 Date 构造，非法输入返回 '-'）
 */
function formatYMD(d?: string | Date | null): string {
  if (!d) return '-'
  const dt = typeof d === 'string' ? new Date(d) : d
  if (isNaN(dt.getTime())) return '-'
  const pad = (n: number) => String(n).padStart(2, '0')
  return `${dt.getFullYear()}-${pad(dt.getMonth() + 1)}-${pad(dt.getDate())}`
}
/**
 * 函数级注释：格式化金额（分→元）统一显示
 * 说明：后端金额单位为分，此函数转换为元并保留两位小数。
 * @param n 金额（单位：分，允许 undefined/null）
 * @returns string 元为单位的字符串；入参为空时返回 "-"
 * @throws 无显式异常（Number 转换失败时回退为字符串）
 */
function formatCents(n?: number | null): string {
  if (n === null || n === undefined) return '-'
  const v = Number(n)
  if (Number.isNaN(v)) return '-'
  return (v / 100).toFixed(2)
}

/**
 * 函数级注释：缩短长ID用于表格展示，避免拉伸布局
 * @param v 原始ID字符串或空值
 * @param left 保留左侧字符数，默认 6
 * @param right 保留右侧字符数，默认 4
 * @returns string 缩短后的ID，例如 08de10…06d32a；入参为空返回 "-"
 * @throws 无显式异常（内部使用字符串切片，非法输入时回退为原值）
 */
function shortId(v?: string | null, left = 6, right = 4): string {
  if (!v) return '-'
  const s = String(v)
  if (s.length <= left + right + 1) return s
  return `${s.slice(0, left)}…${s.slice(-right)}`
}

/**
 * 函数级注释：格式化完整时间为人类可读字符串
 * @param v 时间字符串或 Date
 * @returns string 形如 YYYY-MM-DD HH:mm:ss；入参为空返回 "-"
 * @throws 无显式异常（非法输入时回退原值或 '-'）
 */
function formatDateTime(v?: string | Date | null): string {
  if (!v) return '-'
  const dt = typeof v === 'string' ? new Date(v) : v
  if (isNaN(dt.getTime())) return String(v)
  const pad = (n: number) => String(n).padStart(2, '0')
  const y = dt.getFullYear()
  const m = pad(dt.getMonth() + 1)
  const d = pad(dt.getDate())
  const hh = pad(dt.getHours())
  const mm = pad(dt.getMinutes())
  const ss = pad(dt.getSeconds())
  return `${y}-${m}-${d} ${hh}:${mm}:${ss}`
}

/**
 * 函数级注释：短时间展示（用于表格省略显示）
 * @param v 时间字符串或 Date
 * @returns string 形如 YYYY-MM-DD HH:mm；入参为空返回 "-"
 * @throws 无显式异常
 */
function shortTime(v?: string | Date | null): string {
  if (!v) return '-'
  const dt = typeof v === 'string' ? new Date(v) : v
  if (isNaN(dt.getTime())) return String(v)
  const pad = (n: number) => String(n).padStart(2, '0')
  const y = dt.getFullYear()
  const m = pad(dt.getMonth() + 1)
  const d = pad(dt.getDate())
  const hh = pad(dt.getHours())
  const mm = pad(dt.getMinutes())
  return `${y}-${m}-${d} ${hh}:${mm}`
}

/**
 * 函数级注释：复制文本到剪贴板
 * @param text 待复制文本
 * @returns Promise<void>
 * @throws 可能抛出权限或环境异常（无剪贴板权限时）
 */
async function copyText(text?: string | null): Promise<void> {
  try {
    const val = text ?? ''
    await navigator.clipboard.writeText(String(val))
    alert('已复制到剪贴板')
  } catch (e) {
    console.error('复制失败', e)
    alert('复制失败，请手动选择并复制')
  }
}
</script>

<style scoped>
/* 页面与头部 */
.container { display: grid; gap: 16px; }
.divided-records { max-width: 1100px; margin: 0 auto; }
.page-header { display: flex; align-items: center; justify-content: space-between; }
.segmented { display: inline-flex; border: 1px solid var(--border); border-radius: 8px; overflow: hidden; background: var(--bg-secondary); }
.segmented-item { height: 32px; padding: 0 14px; cursor: pointer; border: 0; background: transparent; }
.segmented-item.active { background: var(--primary-50); color: var(--primary-700); }

/* 卡片与表单 */
.card { border: 1px solid var(--border); border-radius: 10px; background: var(--card-bg); padding: 12px; }
.filters { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.input { height: 32px; padding: 0 8px; border: 1px solid var(--border); border-radius: 6px; background: var(--bg); }
.btn { height: 32px; padding: 0 12px; border: 1px solid var(--border); border-radius: 6px; background: var(--bg-secondary); cursor: pointer; }
.btn.primary { background: var(--primary-50); color: var(--primary-700); border-color: var(--primary-200); }
.btn.ghost { background: transparent; color: var(--primary-700); border-color: var(--primary-200); }

/* 表格样式 */
.table-wrapper { padding: 0; }
.table { width: 100%; border-collapse: collapse; table-layout: fixed; }
.table thead th { background: var(--bg-secondary); font-weight: 600; }
.table th, .table td { padding: 10px; border-bottom: 1px solid var(--border); text-align: left; }
.table th, .table td { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.table tbody tr.table-row:nth-child(odd) { background: rgba(0,0,0,0.02); }
.mono { font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; font-size: 12px; color: var(--text-secondary); }
.ellipsis { display: inline-block; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.copyable { cursor: copy; }
.table thead th:nth-child(2), .table tbody td:nth-child(2),
.table thead th:nth-child(5), .table tbody td:nth-child(5),
.table thead th:nth-child(6), .table tbody td:nth-child(6),
.table thead th:nth-child(7), .table tbody td:nth-child(7) { width: 160px; }
.table thead th:nth-child(4), .table tbody td:nth-child(4) { width: 180px; }
.amount { font-weight: 600; }
.empty { text-align: center; color: var(--text-secondary); }

/* 分页 */
.pagination { display: flex; align-items: center; gap: 12px; justify-content: space-between; }
</style>


